﻿namespace LambdaCalc.Core.Tests

open System
open NUnit.Framework

open LambdaCalc.Core

[<TestFixture>]
type ``test core-operations: equals``() = 

    let eq = LambdaCalc.Core.Operations.equals

    [<Test>]
    member test.``a = a``() =
        let left = Atom "a"
        let right = Atom "a"
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``a != b``() =
        let left = Atom "a"
        let right = Atom "b"
        let result = eq left right
        Assert.IsFalse(result)

    [<Test>]
    member test.``\x.x = \x.x``() =
        let left = Abstraction("x", Atom "x")
        let right = Abstraction ("x", Atom "x")
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``\x.x = \y.y``() =
        let left = Abstraction("x", Atom "x")
        let right = Abstraction ("y", Atom "y")
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``\x.a = \x.a``() =
        let left = Abstraction("x", Atom "a")
        let right = Abstraction ("x", Atom "a")
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``\x.a != \x.b``() =
        let left = Abstraction("x", Atom "a")
        let right = Abstraction ("x", Atom "b")
        let result = eq left right
        Assert.IsFalse(result)

    [<Test>]
    member test.``ab = ab``() =
        let left = Application(Atom "a", Atom "b")
        let right = Application(Atom "a", Atom "b")
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``ab != ba``() =
        let left = Application(Atom "a", Atom "b")
        let right = Application(Atom "b", Atom "a")
        let result = eq left right
        Assert.IsFalse(result)

    [<Test>]
    member test.``ab != ac``() =
        let left = Application(Atom "a", Atom "b")
        let right = Application(Atom "a", Atom "c")
        let result = eq left right
        Assert.IsFalse(result)

    [<Test>]
    member test.``ab != cb``() =
        let left = Application(Atom "a", Atom "b")
        let right = Application(Atom "c", Atom "b")
        let result = eq left right
        Assert.IsFalse(result)

    [<Test>]
    member test.``\x(ax) = \y(ay)``() =
        let left = Abstraction("x", Application(Atom "a", Atom "x"))
        let right = Abstraction("y", Application(Atom "a", Atom "y"))
        let result = eq left right
        Assert.IsTrue(result)

    [<Test>]
    member test.``\x(xx) != \y(xy)``() =
        let left = Abstraction("x", Application(Atom "x", Atom "x"))
        let right = Abstraction("y", Application(Atom "x", Atom "y"))
        let result = eq left right
        Assert.IsFalse(result)
        
    [<Test>]
    member test.``\xy(xyxy) != \ab(xyab)``() =
        let left = Abstraction("x", Abstraction ("y", Application(Application(Application(Atom "x", Atom "y"), Atom "x"), Atom "y")))
        let right = Abstraction("a", Abstraction ("b", Application( Application (Application (Atom "x", Atom "y"), Atom "a"), Atom "b")))
        let result = eq left right
        Assert.IsFalse(result)
                
    [<Test>]
    member test.``\xy(xx) != \ab(bb)``() =
        let left = Abstraction("x", Abstraction ("y", Application(Atom "x", Atom "x")))
        let right = Abstraction("a", Abstraction ("b", Application(Atom "b", Atom "b")))
        let result = eq left right
        Assert.IsFalse(result)